/*
 * Copyright (c)  2020,  DataPipeline
 * All rights reserved.
 *
 * Id:DefaultTransactionManager.java   2020-07-18 14:34 wanglijun
 */
package cn.datacare.orm.transaction;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * Title: DefaultTransactionManager
 * </p>
 * <p>
 * Description: DefaultTransactionManager
 * (默认的事物管理器，可以管理单个，多个数据源事物，但并不是分布式事物管理器
 * * 不能保证事务统一，只能尽量。)
 * </p>
 * <p>
 * Copyright: Copyright (c) 2020
 * </p>
 * <p>
 * Company/Department: DataPipeline
 * </p>
 *
 * @author wanglijun
 * @version 1.0
 * @since 2020-07-18 14:34
 */
public class DefaultTransactionManager {
    /***
     * 日期
     */
    private static final Logger log = LoggerFactory.getLogger(DefaultTransactionManager.class);

    static ThreadLocal<Boolean> inTrans = ThreadLocal.withInitial(() -> false);

    static ThreadLocal<Map<DataSource, Connection>> mapThreadLocal = new ThreadLocal<>();


    public static void start() {
        inTrans.set(true);
    }

    public static void commit() throws SQLException {
        Map<DataSource, Connection> map = mapThreadLocal.get();
        try {
            if (map == null) {
                return;
            }
            ;
            SQLException e = null;
            for (Connection conn : map.values()) {
                try {
                    conn.commit();

                } catch (SQLException ex) {
                    e = ex;
                } finally {
                    try {
                        conn.close();
                    } catch (SQLException ex) {
                        log.error("commit error of connection " + conn + " " + ex.getMessage(), ex);
                    }

                }

            }
            if (e != null) {
                throw e;
            }
        } finally {
            clear();
        }


    }

    public static void rollback() throws SQLException {
        Map<DataSource, Connection> map = mapThreadLocal.get();
        SQLException e = null;
        if (map == null) {
            return;
        }
        try {
            for (Connection conn : map.values()) {
                try {
                    conn.rollback();
                } catch (SQLException ex) {
                    e = ex;
                } finally {
                    try {
                        conn.close();
                    } catch (SQLException ex) {
                        // TODO Auto-generated catch block
                        ex.printStackTrace();
                    }

                }

            }
            if (e != null) {
                throw e;
            } ;
        } finally {
            clear();
        }


    }

    public static void clear() {
        mapThreadLocal.remove();
        inTrans.remove();
    }

    public static Connection getCurrentThreadConnection(DataSource ds) throws SQLException {
        Map<DataSource, Connection> map = mapThreadLocal.get();
        Connection conn = null;
        if (map == null) {
            map = new HashMap<DataSource, Connection>();
            conn = ds.getConnection();
            //如果用户还有不需要事物，且每次都提交的操作，这个需求很怪，不管了
            conn.setAutoCommit(false);
            map.put(ds, conn);
            mapThreadLocal.set(map);
        } else {
            conn = map.get(ds);
            if (conn != null) {
                return conn;
            }
            conn = ds.getConnection();
            conn.setAutoCommit(false);
            map.put(ds, conn);

        }
        return conn;

    }

    public static boolean inTrans() {
        return inTrans.get();
    }
}
